use std::sync::Arc;

use axum::extract::State;
use axum::{Json, Router};
use axum::routing::post;
use http::HeaderMap;
use sea_orm::JsonValue;
use serde_json::{from_value, Value};
use tokio::sync::Mutex;

use crate::app_state::AppState;
use crate::controller::point_controller::get_machine_index;
use crate::dto::point_dto::{TDQuery, TDSQLQuery};
use crate::util_entity::anyhow_res::{json_success_response, JsonResult};


pub fn route () -> Router<Arc<Mutex<AppState>>> {
    Router::new()
        .route("/GetRetBySqlList", post(get_ret_by_sql_list))
        .route("/GetRetBySingleSql", post(get_ret_by_single_sql))

}
pub async fn get_ret_by_sql_list(
    State(app_state): State<Arc<Mutex<AppState>>>,
    headers: HeaderMap,
    Json(payload): Json<Value>,
) -> JsonResult<Value> {
    let machine_index = get_machine_index(headers);
    let mut param: Vec<TDQuery> = from_value(payload)?;
    let futures: Vec<_> = param.iter().map(|item| {
        let app_state = Arc::clone(&app_state);
        async move {
            let result = app_state.lock().await.td_engine_repo.query(machine_index, item.sql.clone()).await?;
            Ok(result)
        }
    }).collect();
    let results: Vec<Result<Vec<JsonValue>, anyhow::Error>> = futures::future::join_all(futures).await;


    // 检查是否有任何查询失败
    for result in &results {
        if result.is_err() {
            return Err(result.as_ref().unwrap_err().to_string().into());
        }
    }
    // 如果所有查询都成功，获取结果值
    let values: Vec<_> = results.into_iter().enumerate().map(|(index, result)| {
        let result = result.unwrap();
        let new_param: &mut TDQuery = param.get_mut(index).unwrap();
        new_param.ret = Some(result);
        return new_param.clone();
    }).collect();
    Ok(json_success_response(values))
}

pub async fn get_ret_by_single_sql(
    State(app_state): State<Arc<Mutex<AppState>>>,
    headers: HeaderMap,
    Json(payload): Json<Value>,
) ->  JsonResult<Value> {
    let machine_index = get_machine_index(headers);
    let param: TDSQLQuery =  from_value(payload)? ;
    let result = app_state.lock().await.td_engine_repo.query(machine_index, param.sql.clone()).await?;
    Ok(json_success_response(result))
}